package com.lx.service.impl;

import com.lx.model.JwtUser;
import com.lx.model.User;
import com.lx.repository.UserRepository;
import com.lx.service.AuthService;
import com.lx.utils.JwtTokenUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.Objects;

/**
 * @author 段誉
 * @create 2019-06-26 14:43
 */
@Service
public class AuthServiceImpl implements AuthService {
  @Autowired
  private AuthenticationManager authenticationManager;
  @Autowired
  private UserDetailsService userDetailsService;
  @Autowired
  private JwtTokenUtil jwtTokenUtil;
  @Autowired
  private UserRepository userRepository;
  @Autowired
  private PasswordEncoder passwordEncoder;

  @Value("${jwt.tokenHead}")
  private String tokenHead;

  @Override
  public User register(User user) {
    final String username = user.getUsername();
    if (Objects.nonNull(userRepository.findByUsername(username))) {
      return null;
    }

    final String rawPassword = user.getPassword();
    user.setPassword(passwordEncoder.encode(rawPassword));
    user.setLastPasswordResetDate(new Date());
    user.setRoles(Arrays.asList("ROLE_USER"));
    return userRepository.insert(user);
  }

  @Override
  public String login(String username, String password) {
    UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
    final Authentication authentication = authenticationManager.authenticate(upToken);
    SecurityContextHolder.getContext().setAuthentication(authentication);

    final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    final String token = jwtTokenUtil.generateToken(userDetails);
    return token;
  }

  @Override
  public String refresh(String oldToken) {
    final String token = oldToken.substring(tokenHead.length());
    String username = jwtTokenUtil.getUsernameFromToken(token);
    JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username);
    if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())) {
      return jwtTokenUtil.refreshToken(token);
    }
    return null;
  }
}
